"""Unit and regression tests for the generator module."""

import unittest

from dwgen.generator import (
    get_word_dict,
    generate_password,
    generate_passphrase,
)


class GetWordDictTests(unittest.TestCase):

    """Unit and regression tests for the get_word_dict() function."""

    def test_unsupported_language(self):
        with self.assertRaisesRegex(ValueError, "unsupported language 'foo'"):
            get_word_dict('foo')

    def test_de(self):
        wd = get_word_dict('de')
        self.assertEqual(len(wd), 6**5)
        target_words = ['iod', 'iok', 'ion', 'ionen', 'iowa', 'ip']
        for i, target_word in enumerate(target_words, 1):
            self.assertEqual(wd[33330 + i], target_word)

    def test_en(self):
        wd = get_word_dict('en')
        self.assertEqual(len(wd), 6**5)
        target_words = ['hoyt', 'hp', 'hq', 'hr', 'hs', 'ht']
        for i, target_word in enumerate(target_words, 1):
            self.assertEqual(wd[33330 + i], target_word)

    def test_en_beale(self):
        wd = get_word_dict('en-beale')
        self.assertEqual(len(wd), 6**5)
        target_words = ['humps', 'hums', 'humus', 'hun', 'hunch', 'hung']
        for i, target_word in enumerate(target_words, 1):
            self.assertEqual(wd[33330 + i], target_word)

    def test_sv(self):
        wd = get_word_dict('sv')
        self.assertEqual(len(wd), 6**5)
        target_words = ['kasta', 'kastby', 'kasus', 'katet', 'katig', 'katod']
        for i, target_word in enumerate(target_words, 1):
            self.assertEqual(wd[33330 + i], target_word)


class GeneratePasswordTests(unittest.TestCase):

    """Unit and regression tests for the get_password() function."""

    def test_unsupported_language(self):
        with self.assertRaisesRegex(ValueError, "unsupported language 'foo'"):
            generate_password('foo')

    def test_default_language(self):
        self.assertIn(generate_password(), get_word_dict('en').values())

    def test_de(self):
        self.assertIn(generate_password('de'), get_word_dict('de').values())

    def test_en(self):
        self.assertIn(generate_password('en'), get_word_dict('en').values())

    def test_en_beale(self):
        password = generate_password('en-beale')
        self.assertIn(password, get_word_dict('en-beale').values())

    def test_sv(self):
        self.assertIn(generate_password('sv'), get_word_dict('sv').values())


class GeneratePassphraseTests(unittest.TestCase):

    """Unit and regression tests for the generate_passphrase() function."""

    def test_unsupported_language(self):
        with self.assertRaisesRegex(ValueError, "unsupported language 'foo'"):
            generate_passphrase(1, language='foo')

    def test_default_language(self):
        passphrase = generate_passphrase(2).split()
        password_choices = get_word_dict('en').values()
        self.assertTrue(all(pw in password_choices for pw in passphrase))

    def test_de(self):
        passphrase = generate_passphrase(2, language='de').split()
        password_choices = get_word_dict('de').values()
        self.assertTrue(all(pw in password_choices for pw in passphrase))

    def test_en(self):
        passphrase = generate_passphrase(2, language='en').split()
        password_choices = get_word_dict('en').values()
        self.assertTrue(all(pw in password_choices for pw in passphrase))

    def test_en_beale(self):
        passphrase = generate_passphrase(2, language='en-beale').split()
        password_choices = get_word_dict('en-beale').values()
        self.assertTrue(all(pw in password_choices for pw in passphrase))

    def test_sv(self):
        passphrase = generate_passphrase(2, language='sv').split()
        password_choices = get_word_dict('sv').values()
        self.assertTrue(all(pw in password_choices for pw in passphrase))

    def test_zero_words(self):
        self.assertEqual(generate_passphrase(0), '')

    def test_one_word(self):
        passphrase = generate_passphrase(1)
        self.assertGreater(len(passphrase), 0)
        self.assertEqual(passphrase.count(' '), 0)

    def test_two_words(self):
        passphrase = generate_passphrase(2)
        self.assertGreater(len(passphrase), 0)
        self.assertEqual(passphrase.count(' '), 1)

    def test_custom_separator(self):
        passphrase = generate_passphrase(2, separator='\t')
        self.assertGreater(len(passphrase), 0)
        self.assertEqual(passphrase.count('\t'), 1)
